﻿#region Copyright (c) 2000-2008 Developer Express Inc.
/*
{*******************************************************************}
{                                                                   }
{       Developer Express .NET Component Library                    }
{       AgDataGrid                                 }
{                                                                   }
{       Copyright (c) 2000-2008 Developer Express Inc.              }
{       ALL RIGHTS RESERVED                                         }
{                                                                   }
{   The entire contents of this file is protected by U.S. and       }
{   International Copyright Laws. Unauthorized reproduction,        }
{   reverse-engineering, and distribution of all or any portion of  }
{   the code contained in this file is strictly prohibited and may  }
{   result in severe civil and criminal penalties and will be       }
{   prosecuted to the maximum extent possible under the law.        }
{                                                                   }
{   RESTRICTIONS                                                    }
{                                                                   }
{   THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES           }
{   ARE CONFIDENTIAL AND PROPRIETARY TRADE                          }
{   SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS   }
{   LICENSED TO DISTRIBUTE THE PRODUCT AND ALL ACCOMPANYING .NET    }
{   CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY.                 }
{                                                                   }
{   THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED      }
{   FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE        }
{   COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE       }
{   AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT  }
{   AND PERMISSION FROM DEVELOPER EXPRESS INC.                      }
{                                                                   }
{   CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON       }
{   ADDITIONAL RESTRICTIONS.                                        }
{                                                                   }
{*******************************************************************}
*/
#endregion Copyright (c) 2000-2008 Developer Express Inc.

using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using DevExpress.AgDataGrid.Data.Helpers;
using System.Collections.Generic;
namespace DevExpress.AgDataGrid.Data {
	public abstract class BaseSelectionCollection<T> : IDisposable {
		SelectionController selectionController;
		Dictionary<T, object> rows;
		public BaseSelectionCollection(SelectionController selectionController) {
			this.selectionController = selectionController;
		}
		protected DataController Controller { get { return SelectionController == null ? null : SelectionController.Controller; } }
		protected SelectionController SelectionController { get { return selectionController; } }
		protected Dictionary<T, object> Rows {
			get {
				if(rows == null) rows = new Dictionary<T, object>();
				return rows;
			}
		}
		public int Count { get { return rows == null ? 0 : rows.Count; } }
		protected virtual void OnSelectionChanged(SelectionChangedEventArgs e) {
			if(SelectionController != null) SelectionController.OnSelectionChanged(e);
		}
		public void Clear() {
			if(Count == 0) return;
			Rows.Clear();
			OnSelectionChanged(SelectionChangedEventArgs.Refresh);
		}
		public void Dispose() {
			Clear();
			selectionController = null;
		}
		protected abstract T GetRowObjectByControllerRow(int controllerRow);
		protected abstract bool IsRowObjectValid(T row);
		public object GetRowSelectedObject(int controllerRow) {
			T row = GetRowObjectByControllerRow(controllerRow);
			return !IsRowObjectValid(row) ? null : GetSelectedObject(row);
		}
		public bool GetRowSelected(int controllerRow) {
			T row = GetRowObjectByControllerRow(controllerRow);
			return !IsRowObjectValid(row) ? false : GetSelected(row);
		}
		public void SetRowSelected(int controllerRow, bool selected, object selectionObject) {
			T row = GetRowObjectByControllerRow(controllerRow);
			if(!IsRowObjectValid(row)) return;
			SetSelected(controllerRow, row, selected, selectionObject);
		}
		protected object GetSelectedObject(T row) {
			if(Count == 0) return null;
			return Rows[row];
		}
		protected bool GetSelected(T row) {
			if(Count == 0) return false;
			return Rows.ContainsKey(row);
		}
		protected void SetSelected(int controllerRow, T row, bool selected, object selectionObject) {
			if(GetSelected(row) == selected) {
				if(selected && selectionObject != null) {
					if(Object.Equals(GetSelectedObject(row), selectionObject)) return;
				} else
					return;
			}
			if(!selected) {
				Rows.Remove(row);
			} else {
				Rows[row] = selectionObject;
			}
			OnSelectionChanged(new SelectionChangedEventArgs(selected ? NotifyCollectionChangedAction.Add : NotifyCollectionChangedAction.Remove, controllerRow));
		}
	}
	public class SelectedRowsCollection : BaseSelectionCollection<int> {
		public SelectedRowsCollection(SelectionController selectionController) : base(selectionController) { }
		protected override int GetRowObjectByControllerRow(int controllerRow) {
			int row = Controller.GetListSourceRowIndex(controllerRow);
			return row;
		}
		protected override bool IsRowObjectValid(int row) {
			return row != DataController.InvalidRow;
		}
		public void CopyToArray(int[] array, int startIndex) {
			if(Count > 0) Rows.Keys.CopyTo(array, startIndex);
		}
	}
	public class SelectedGroupsCollection : BaseSelectionCollection<GroupRowInfo> {
		public SelectedGroupsCollection(SelectionController selectionController) : base(selectionController) { }
		protected override GroupRowInfo GetRowObjectByControllerRow(int controllerRow) {
			return Controller.GroupInfo.GetGroupRowInfoByHandle(controllerRow);
		}
		protected override bool IsRowObjectValid(GroupRowInfo row) {
			return row != null;
		}
		internal void OnGroupDeleted(GroupRowInfo groupInfo) {
			SetSelected(0, groupInfo, false, null);
		}
		internal void OnReplaceGroupSelection(GroupRowInfo oldGroupInfo, GroupRowInfo newGroupInfo) {
			if(!GetSelected(oldGroupInfo)) return;
			if(newGroupInfo == null) {
				OnGroupDeleted(oldGroupInfo);
				return;
			}
			Rows.Remove(oldGroupInfo);
			Rows[newGroupInfo] = null;
		}
		public void CopyToArray(int[] array, int startIndex) {
			if(Count == 0) return;
			int n = startIndex;
			foreach(GroupRowInfo group in Rows.Keys) {
				array[n] = group.Handle;
				n++;
			}
		}
	}
	public class SelectionController : IDisposable {
		DataController controller;
		SelectedRowsCollection selectedRows;
		SelectedGroupsCollection selectedGroupRows;
		public SelectionController(DataController controller) {
			this.controller = controller;
			this.selectedRows = new SelectedRowsCollection(this);
			this.selectedGroupRows = new SelectedGroupsCollection(this);
		}
		protected internal SelectedRowsCollection SelectedRows { get { return selectedRows; } }
		protected internal SelectedGroupsCollection SelectedGroupRows { get { return selectedGroupRows; } }
		protected internal DataController Controller { get { return controller; } }
		public void Dispose() {
			this.controller = null;
			this.selectedGroupRows.Dispose();
			this.selectedRows.Dispose();
			this.selectedGroupRows = null;
			this.selectedRows = null;
		}
		protected internal virtual void OnSelectionChanged(SelectionChangedEventArgs e) {
			Controller.OnSelectionChanged(e);
		}
		public int Count { get { return SelectedRows.Count + SelectedGroupRows.Count; } }
		public bool GetSelected(int controllerRow) {
			if(Controller.IsGroupRowHandle(controllerRow))
				return SelectedGroupRows.GetRowSelected(controllerRow);
			return SelectedRows.GetRowSelected(controllerRow);
		}
		public object GetSelectedObject(int controllerRow) {
			if(Controller.IsGroupRowHandle(controllerRow))
				return SelectedGroupRows.GetRowSelectedObject(controllerRow);
			return SelectedRows.GetRowSelectedObject(controllerRow);
		}
		public void SetSelected(int controllerRow, bool selected) {
			SetSelected(controllerRow, selected, true);
		}
		public void SetSelected(int controllerRow, bool selected, object selectionObject) {
			if(Controller.IsGroupRowHandle(controllerRow)) {
				SelectedGroupRows.SetRowSelected(controllerRow, selected, selectionObject);
				return;
			}
			SelectedRows.SetRowSelected(controllerRow, selected, selectionObject);
		}
		public void Clear() {
			if(Count == 0) return;
			SelectedGroupRows.Clear();
			SelectedRows.Clear();
		}
		public void SelectAll() {
			Clear();
			for(int n = 0; n < Controller.VisibleRowCount; n++) 
				SetSelected(Controller.GetControllerRowHandle(n), true);
		}
		public int[] GetSelectedRows() {
			if(Count == 0) return new int[0];
			int[] res = new int[Count];
			SelectedRows.CopyToArray(res, 0);
			for(int n = SelectedRows.Count - 1; n >= 0; n--) 
				res[n] = Controller.GetControllerRow(res[n]);
			SelectedGroupRows.CopyToArray(res, SelectedRows.Count);
			Array.Sort(res);
			return res;			
		}
		internal void SelectRange(int startRow, int endRow) {
			if(!Controller.IsValidControllerRowHandle(startRow)) {
				SetSelected(endRow, true);
				return;
			}
			if(!Controller.IsValidControllerRowHandle(endRow)) return;
			int row = Controller.GetVisibleIndex(startRow);
			int end = Controller.GetVisibleIndex(endRow);
			if(row > end) {
				int tmp = end;
				end = row;
				row = tmp;
			}
			while(row != end) {
				SetSelected(Controller.GetControllerRowHandle(row), true);
				row++;
			}
			SetSelected(Controller.GetControllerRowHandle(row), true);
		}
	}
}
